{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}

module Aria2.Bytes where

import Data.Semigroup (Sum (..))
import Data.Word (Word16, Word32, Word64)

newtype Bytes = B {unB :: Word64}
  deriving stock (Show)
  deriving newtype (Eq, Ord)
  deriving (Semigroup, Monoid) via (Sum Word64)

pattern Bytes :: Word64 -> Bytes
pattern Bytes w <-
  (unB -> w)
  where
    Bytes w = B w

pattern KiloBytes :: Word32 -> Bytes
pattern KiloBytes w <-
  (fmap fromIntegral . (`divNoRem` bytesInK) . unB -> Just w)
  where
    KiloBytes w = B . fromIntegral . (* bytesInK) $ w

pattern MegaBytes :: Word16 -> Bytes
pattern MegaBytes w <-
  (fmap fromIntegral . (`divNoRem` bytesInM) . unB -> Just w)
  where
    MegaBytes w = B . fromIntegral . (* bytesInM) $ w

-- Helpers

divNoRem :: (Integral a) => a -> a -> Maybe a
divNoRem x d = case x `divMod` d of
  (y, 0) -> Just y
  _ -> Nothing

bytesInK :: (Integral a) => a
bytesInK = 1024

bytesInM :: (Integral a) => a
bytesInM = 1024 * 1024
